package okw.network;

import java.io.IOException;
import java.io.ObjectInputStream;

import okw.database.DatabaseManager;
import okw.gui.MainWindowO;

import core.messages.*;


/**
 * 
 * @author Maks
 * W�tek odpowiedzialny za odbieranie wiadomosci od centrali, przychodz�cych z g�ry, 
 * na razie tylko potwierdze�, do zmiany potem
 * 
 */

public class ServerReceiver implements Runnable {
	ConnectionO cm = null;
	Queue2 queue2 = null;
	StanO stanO = null;
	Terminal serwerTerm = null;
	
	public ServerReceiver(Terminal serw, ConnectionO cm, Queue2 queue2, StanO stanO){
		this.cm = cm;
		this.queue2 = queue2;
		this.stanO = stanO;
		this.serwerTerm = serw;
	}
	
	// obsluguje odebranie glosu NIE POTRZEBNE
	public void odebranoGlos(VoteMsg message) throws Exception{

		Ack ack = new Ack(stanO.getNr(), message.getNumber());
		cm.sendUp(ack);
	}
	
	// obsluguje odebrania potwierdzen
	public void odebranoPotwierdzenie(Ack ack){
		if(ack!=null){
			System.out.println("Otrzymano potwierdzenie od centrali dla nr:msg: " + ack.getNumber() + " " + ack.getReceived());
		} else{
			System.out.println("Nie otrzymano potwierdzenia!");
		}
	}

	public void odebranoDane(Dane data) throws Exception{
		
		// Tu odbieramy dane i wysylamy potwirdzenie odebrania.
		// Dane znajduje sie oczywiscie w zmiennej data
		// mozesz tu sobie z nimi robic co chcesz byle nie usuwac tych pieciu ponizszych linijek
		
		DatabaseManager db = DatabaseManager.getInstance();
		if (data.getElectionData() != null) {
			if (db.canSavaElectionData(data.getElectionData().getElection().getName())) {
				db.saveElectionData(data.getElectionData());
				System.out.println("Otrzymano dane do glosowania od centrali nr:msg: " + data.getNumber() + " " + data.getType());
				MainWindowO.electionNr = db.getSelectedElectionId(MainWindowO.token);
				System.out.println("ELENR2: " + MainWindowO.electionNr + " " + MainWindowO.token);
				stanO.setDaneWyborcze(true);
			} 
		}
		
		Ack ack = new Ack(stanO.getNr(), data.getNumber());
		ack.setInfoNr(2);
		cm.sendUp(ack);
		MainWindowO.czyWlaczonyILista();
		MainWindowO.aktualizujGlosujacych();
		MainWindowO.aktualizujTerminale();
	}
	
	// obsluguje odbieranie informacji
	private void odebranoInformacje(Info info) throws Exception {
		if(info != null){
			System.out.println("Komisja otrzymala od centrali informacje: " + info.getNumber() + " : " + info.getMsg());
		}
		switch(info.getMsg()){
		case 0:{
			// info ze polaczono z serwerem
			MainWindowO.polaczono();
			stanO.setPolaczenie(true);
			System.out.println("Komisja wysyla potwierdzenie powitania");
			Ack ack = new Ack(stanO.getNr(), info.getNumber());
			cm.sendUp(ack);
			break;
		}
		case 1:{
			// info od serwera, ze mozna zaczac glosowac - nieuzywane
			if(!stanO.isGlosowanieRozpoczete()){
				MainWindowO.gotowoscGlosowania();
				//stanO.setZaczacGlosowanie(true);
			}
			//stanO.setZakonczycGlosowanie(false);
			System.out.println("Komisja zostala poproszona o glosowanie");
			Ack ack = new Ack(stanO.getNr(), info.getNumber());
			cm.sendUp(ack);
			break;
		}
		case 2:
		{
			// info od serwera, ze trzeba konczyc glosowanie - nieuzywane
			if(!stanO.isKonczenieGlosowania()){
				MainWindowO.konczenieGlosowania();
				//stanO.setZakonczycGlosowanie(true);
			}
			//stanO.setZaczacGlosowanie(false);
			System.out.println("Komisja zostala poproszona o zakonczenie glosowania");
			Ack ack = new Ack(stanO.getNr(), info.getNumber());
			cm.sendUp(ack);;
			break;
		}
		case 3:{
			// test z ckw, prosba o zwrocenie ilosci terminali aktwynych i nieakt
			int ile = cm.getTerminale().size();
			int ileAkt = 0;
			for(Terminal t: cm.getTerminale()){
				if(t.getStan() != null && t.getStan().isPolaczenie())
					ileAkt++;
			}
			TestMsg tmsg = new TestMsg(stanO.getNr(), ile, ileAkt);
			cm.sendUp(tmsg);
			Ack ack = new Ack(stanO.getNr(), info.getNumber());
			cm.sendUp(ack);;
			break;
		}
		}
	}
	
	private void odebranoZamiejscowego(NonresidentMsg message) throws Exception  {
		System.out.println("ADRES " + message.getAdres());
		NonresidentThread.setNonresidentMsg(message);
		NonresidentThread.setCzyDane(true);
		Ack ack = new Ack(stanO.getNr(), message.getNumber());
		cm.sendUp(ack);;
	}
	
	public void run() {
		try{
			serwerTerm.getSocket().setSoTimeout(2000);
			serwerTerm.setOis(new ObjectInputStream(serwerTerm.getSocket().getInputStream()));
			serwerTerm.getSocket().setSoTimeout(0);
			
			while(true){ 
				// sprawdzamy typ wiadomosci
				Object message = serwerTerm.getOis().readObject();
				if(message.getClass().equals(VoteMsg.class))
					odebranoGlos((VoteMsg)message);
				if(message.getClass().equals(Ack.class)){
					queue2.findToRemove((Ack)message);
					odebranoPotwierdzenie((Ack)message);
				}
				if(message.getClass().equals(Info.class))
					odebranoInformacje((Info)message);
				if(message.getClass().equals(Dane.class))
					odebranoDane((Dane)message);
				if(message.getClass().equals(NonresidentMsg.class))
					odebranoZamiejscowego((NonresidentMsg)message);
				
			}		
			
		} catch (Exception e){
			e.printStackTrace();
			e.getMessage();
			MainWindowO.bladPolaczenia();
			try {
				if(serwerTerm.getSocket()!=null){
					serwerTerm.getSocket().close();
					serwerTerm.setSocket(null);
				}
				if(serwerTerm.getOos()!=null){
					serwerTerm.getOos().close();
					serwerTerm.setOos(null);
				}
				if(serwerTerm.getOis()!=null){
					serwerTerm.getOis().close();
					serwerTerm.setOis(null);
				}
				System.out.println("Zamykam polaczenie...");
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			stanO.setPolaczenie(false);
		}
		System.out.println("Koniec nasluchiwania od serwera");
	}

}


